import { MathUtils, Mesh, Vector2, Raycaster, Group } from "three"
import { TransformControls } from "three/addons/controls/TransformControls"; //可视化平移控件

export default class Transform {
    constructor(viewer) {
        this.viewer = viewer
        this.control = undefined
        this.activeObject = null
        this.mouse = undefined
        this.raycaster = undefined
        this.keydownListener = undefined
        this.keyupListener = undefined
        this.dblclickListener = undefined
        this.deleteListener = undefined

        this.#init()
    }

    #init() {
        this.control = new TransformControls(
            this.viewer.camera,
            this.viewer.renderer.domElement
        );
        this.mouse = new Vector2(); // 创建鼠标坐标
        this.raycaster = new Raycaster(); // 创建射线
        this.createTransFormControls(this)
        this.addKeydownListener()
        this.addKeyupListener()
        this.addDblclickListener()
        this.addDeleteListener()
    }

    createTransFormControls(that) {
        this.control.addEventListener("change", () => { });
        this.control.addEventListener("dragging-changed", function (event) {
            that.viewer.orbitControl.enabled = !event.value;
        });
        this.control.addEventListener("objectChange", (param) => { });
        this.viewer.scene.add(this.control);
    };

    addKeydownListener() {
        this.keydownListener = this.#keydownEvent.bind(this, this)
        // this.viewer.viewerDom.addEventListener("keydown", this.keydownListener)
        window.addEventListener("keydown", this.keydownListener)
    }

    addKeyupListener() {
        this.keyupListener = this.#keyupEvent.bind(this, this)
        window.addEventListener("keyup", this.keyupListener)
    }

    addDblclickListener() {
        this.keyupListener = this.#dblclickEvent.bind(this, this)
        this.viewer.viewerDom.addEventListener("dblclick", this.keyupListener)
    }

    addDeleteListener() {
        this.deleteListener = this.#deleteEvent.bind(this, this)
        window.addEventListener("keydown", this.deleteListener)
    }

    #keydownEvent(that, event) {
        switch (event.key) {
            case "q":
                that.control.setSpace(
                    that.control.space === "local" ? "world" : "local"
                );
                break;

            case "Shift":
                that.control.setTranslationSnap(1);
                that.control.setRotationSnap(MathUtils.degToRad(15));
                that.control.setScaleSnap(0.25);
                break;

            case "w":
                that.control.setMode("translate");
                break;

            case "e":
                that.control.setMode("rotate");
                break;

            case "r":
                that.control.setMode("scale");
                break;

            case "c":
                that.viewer.changeCamera(() => {
                    that.control.camera = that.viewer.camera
                });
                break;

            case "v":
                const randomFoV = Math.random() + 0.1;
                const randomZoom = Math.random() + 0.1;

                that.viewer.cameraPersp.fov = randomFoV * 160;
                that.viewer.cameraOrtho.bottom = -randomFoV * 500;
                that.viewer.cameraOrtho.top = randomFoV * 500;

                that.viewer.cameraPersp.zoom = randomZoom * 5;
                that.viewer.cameraOrtho.zoom = randomZoom * 5;
                break;

            case "+":
            case "=":
                that.control.setSize(that.control.size + 0.1);
                break;

            case "-":
            case "_":
                that.control.setSize(Math.max(that.control.size - 0.1, 0.1));
                break;

            case "x":
                that.control.showX = !that.control.showX;
                break;

            case "y":
                that.control.showY = !that.control.showY;
                break;

            case "z":
                that.control.showZ = !that.control.showZ;
                break;

            case " ":
                that.control.enabled = !that.control.enabled;
                break;

            case "Escape":
                that.control.reset();
                break;
        }
    }

    #keyupEvent(that, event) {
        switch (event.key) {
            case "Shift":
                that.control.setTranslationSnap(null);
                that.control.setRotationSnap(null);
                that.control.setScaleSnap(null);
                break;
        }
    }

    #dblclickEvent(that, event) {
        const { clientHeight, clientWidth } = that.viewer.viewerDom;
        // 计算鼠标在屏幕上的坐标
        that.mouse.x = (event.offsetX / clientWidth) * 2 - 1;
        that.mouse.y = -(event.offsetY / clientHeight) * 2 + 1;
        that.raycaster.setFromCamera(that.mouse, that.viewer.camera); // 设置射线的起点和终点
        let object;

        const intersects = that.raycaster.intersectObjects(that.viewer.objects, true); // 检测射线与模型是否相交
        if (intersects.length > 0 && intersects[0]) {
            object = that.#getParentGroup(intersects[0].object)
            if (object) {
                if (object !== that.activeObject) {
                    that.control.attach(object);
                    that.activeObject = object;
                    return;
                }
            }
        }

        const intersects1 = that.raycaster.intersectObjects(that.viewer.pipes, true); // 检测射线与管道是否相交
        if (intersects1.length > 0 && intersects1[0]) {
            if (intersects1[0].object instanceof Mesh) {
                object = intersects1[0].object;
                if (object !== that.activeObject) {
                    that.control.attach(object);
                    that.activeObject = object;
                    return;
                }
            }
        }
    }

    #deleteEvent(that, event) {
        if (event.key === 'Delete') {
            if (that.activeObject === null) {
                ElMessage.error("未选中模型！");
            } else {
                that.viewer.objects.some((item, index) => {
                    if (item.uuid === that.activeObject.uuid) {
                        that.viewer.objects.splice(index, 1);
                        return true;
                    }
                });
                that.viewer.pipes.some((item, index) => {
                    if (item.uuid === that.activeObject.uuid) {
                        that.viewer.pipes.splice(index, 1);
                        return true;
                    }
                });

                that.control.detach(that.activeObject);
                that.viewer.scene.remove(that.activeObject);
                that.activeObject = null;
                ElMessage.success("删除一个模型");
            }
        }
    }

    #getParentGroup(object) {
        if (object.parent instanceof Group) {
            return object.parent
        } else if (object.parent.parent instanceof Group) {
            return object.parent.parent
        } else if (object.parent.parent.parent instanceof Group) {
            return object.parent.parent.parent
        } else if (object.parent.parent.parent.parent instanceof Group) {
            return object.parent.parent.parent.parent
        }
    }
}